﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;
using System.Web;

namespace TheCup
{
    [Table("Rounds")]
    [JsonObject(IsReference = true)]
    public class Round
    {
        [Key]
        [Column("no")]
        public int Id { get; set; }

        [Obsolete]
        [Column("id")]
        public Guid uuid { get; set; }

        [DataType(DataType.Date)]
        public DateTime DateEntry { get; set; }

        public bool IsPrivate { get; set; }

        [Column("PlayerNo")]
        public int PlayerId { get; set; }
                
        [ForeignKey("PlayerId")]
        public virtual Player Editor { get; set; }

        [Column("CourseNo")]
        [Required]
        public int CourseId { get; set; }

        [ForeignKey("CourseId")]
        public virtual Course Course { get; set; }

        [Column("EventNo")]
        public Nullable<int> EventId { get; set; }

        [ForeignKey("EventId")]
        public virtual Event Event { get; set; }
        
        [NotMapped]
        public CommentsViewModel Comments { get; set; }

        public DateTime Created { get; set; }

        public void ApplyRules()
        {
            ApiControllers.PlayerController pc = new ApiControllers.PlayerController();
            Player player = pc.GetLoggedInPlayer();
            this.PlayerId = player.Id;
        }

        public bool EditingAllowed()
        {
            return this.Created > DateTime.UtcNow.AddDays(-14);
        }

        public bool DeletingAllowed()
        {
            return this.Created > DateTime.UtcNow.AddDays(-14);
        }

        public int NumberOfScorecards
        {
            get
            {
                return Scorecards == null ? 0 : Scorecards.Count;
            }
        }

        public void CalculateOrderOfMeritPointsByNettoScore()
        {
            List<Scorecard> winners = this.Scorecards.Where(sc => sc.PositionByNettoscore == 1).ToList<Scorecard>();
            if (winners.Count > 0)
            {
                int winnerscore = Convert.ToInt32(winners.FirstOrDefault().NettoScore);
                int purse = Convert.ToInt32(this.Scorecards.Where(sc => sc.PositionByNettoscore > 1).ToList<Scorecard>().Sum(m => (m.NettoScore - winnerscore) * 2));

                foreach (Scorecard e in winners)
                {
                    e.OrderOfMeritPoints = purse / winners.Count;
                }
            }
        }

        public void CalculatePositionsByNettoscore()
        {
            int pos = 0;
            Nullable<decimal> prevval = 0;
            foreach (Scorecard e in this.Scorecards.OrderBy(ns => ns.NettoScore))
            {
                if (e.NettoScore != prevval)
                {
                    pos++;
                    prevval = e.NettoScore;
                }
                e.PositionByNettoscore = pos;
                e.PositionByNettoscorePrintable = pos.ToString();
            }

            // get duplicate positions and mark with 'T'
            var dups = this.Scorecards.GroupBy(x => x.PositionByNettoscore).Where(grp => grp.Count() > 1).Select(group => group);

            foreach (var d in dups)
            {
                this.Scorecards.Where(el => el.PositionByNettoscore == d.Key).Select(tp => { tp.PositionByNettoscorePrintable = "T" + tp.PositionByNettoscore; return tp; }).ToList();
            }
        }

        public void PrepareScorecardsForRankingLists()
        {
            this.CalculatePositionsByNettoscore();
            this.CalculateOrderOfMeritPointsByNettoScore();

            //@Points = ((@PtsTotal/@Nettoscore)*36)+((@Players+1)-@Position)
            foreach (Scorecard e in this.Scorecards.OrderBy(ns => ns.NettoScore))
            {
                e.TrophyListPoints = ((e.StablefordPoints / e.NettoScore.Value) * 36) + ((this.NumberOfScorecards + 1) - e.PositionByNettoscore);
            }
        }

        public virtual List<Scorecard> Scorecards { get; set; }

        public enum RoundType
        {
            Private,
            Official,
            Both
        }
    }
}